#!/usr/bin/env python

import os
import wx

import louise.viewer

from _base import Base
from resources import icons
from resources.strings import viewer as r

class Viewer(Base):
    
    MAX_WIDTH = 1308
    CHANNEL_WIDTH = 52
    
    _lineId = wx.NewId()
    _data = None
    _step = 1
    _y = None
    _samplingRate = 0
    _path = None
    
    def __init__(self, view, interactor):
        super(Viewer, self).__init__(view, interactor)
        config = louise.viewer.Config()
        self.restoreSize(config)
        self.restorePosition(config)
        self.restoreSetting(config)
        view.Icon = icons.Viewer.Icon
        view.Title = r.description
    
    def restoreSetting(self, config):
        toolbar = self.view.ToolBar
        self._amplitudeZoom = config.ReadInt('Zoom/Amplitude', 1)
        toolbar.amplitude.Value = '%s' % self._amplitudeZoom
        self._timeZoom = config.ReadInt('Zoom/Time', 1)
        toolbar.time.Value = '%s' % self._timeZoom
        
    def saveSetting(self, config):
        toolbar = self.view.ToolBar
        config.WriteInt('Zoom/Amplitude', self._amplitudeZoom)
        config.WriteInt('Zoom/Time', self._timeZoom)
        
    def onClose(self):
        config = louise.viewer.Config()
        self.savePosition(config)
        self.saveSize(config)
        self.saveSetting(config)
    
    def open(self):
        self._path = self.view.fileDialog(wildcard='*.txt')
        if not self._path: return
        
        self.view.Title = 'Viewer - %s' % self._path
        self.draw(self._path)
    
    def draw(self, path):
        if not path: return
        self.view.busyInfo('Drawing...')
        
        amplitudeZoom = int(self.view.ToolBar.amplitude.Value)
        timeZoom = int(self.view.ToolBar.time.Value)
        
        f = open(path, 'r')
        lines = [line.strip() for line in f.readlines()]
        f.close()
        
        canvas = self.view.canvas
        pdc = canvas.pdc
        pdc.RemoveAll()
        
        self._data = []
        for line in lines:
            if 'Sampling Rate (ms):' in line:
                data = line.split(':')
                self._samplingRate = float(data[1].strip())
                continue
            else:
                data = line.split('\t')
            if data[0] != 'Data:': continue
            
            self._data.append(data)
            
        canvas.Scroll(0, 0)
        canvas.maxHeight = (self._step * len(self._data)) / timeZoom
        canvas.maxWidth = self.MAX_WIDTH
        canvas.SetVirtualSize((canvas.maxWidth, canvas.maxHeight))
        canvas.pdc.BeginDrawing()
        
        previousData = None
        y = 0
        counter = 0
        dc = wx.ScreenDC()
        for data in self._data:
            counter += 1
            if (counter % (200 * timeZoom)) == 0:
                pdc.SetPen(wx.Pen(wx.NamedColour('red'), 1))
                pdc.DrawLine(60, y + self._step, self.CHANNEL_WIDTH * 24 + 60,
                             y + self._step)
                t = '%2.0f ms' % (counter * self._samplingRate)
                w, h = dc.GetTextExtent(t)
                pdc.DrawText(t, 65 - w, y - h / 2)
            if timeZoom != 1:
                if (counter % timeZoom) != 1: continue
            if previousData:
                y0 = y
                y += self._step
                for i in range(24):
                    addition = i * self.CHANNEL_WIDTH
                    x0  = int(previousData[i + 1]) * amplitudeZoom
                    x0 += 32767
                    x0 = (x0 * self.CHANNEL_WIDTH) / 65535
                    if x0 > self.CHANNEL_WIDTH: x0 = self.CHANNEL_WIDTH
                    elif x0 < 0: x0 = 0
                    x0 += addition + 60
                    x = int(data[i + 1]) * amplitudeZoom
                    x += 32767
                    x = (x * self.CHANNEL_WIDTH) / 65535
                    if x > self.CHANNEL_WIDTH: x = self.CHANNEL_WIDTH
                    elif x < 0: x = 0
                    x += addition + 60
                    pdc.SetPen(wx.Pen(wx.NamedColour('black'), 1))
                    pdc.DrawLine(int(x0), y0, int(x), y)
            previousData = data
                
        pdc.SetId(self._lineId)
        pdc.RemoveId(self._lineId)
        pdc.SetPen(wx.Pen(wx.NamedColour('blue'), 1))
        pdc.DrawLine(60, 0, self.MAX_WIDTH, 0)
        r = wx.Rect(60, 0, self.MAX_WIDTH, 0)
        r.Inflate(4, 4)
        pdc.SetIdBounds(self._lineId, r)
        
        canvas.pdc.EndDrawing()
        canvas.Refresh()
        
        self.view.idle()
    
    def offsetRect(self, r):
        canvas = self.view.canvas
        xView, yView = canvas.GetViewStart()
        xDelta, yDelta = canvas.GetScrollPixelsPerUnit()
        r.OffsetXY(-(xView * xDelta), -(yView * yDelta))
        
    def convertEventCoords(self, x, y):
        canvas = self.view.canvas
        xView, yView = canvas.GetViewStart()
        xDelta, yDelta = canvas.GetScrollPixelsPerUnit()
        return (x + (xView * xDelta), y + (yView * yDelta))

    def move(self, position):
        pdc = self.view.canvas.pdc
        r = pdc.GetIdBounds(self._lineId)
        x, y = self.convertEventCoords(position[0], position[1])
        dx = x - r.x - (r.width / 2)
        dy = y - r.y - (r.height / 2)
        pdc.TranslateId(self._lineId, 0, dy)
        r2 = pdc.GetIdBounds(self._lineId)
        r = r.Union(r2)
        r.Inflate(4, 4)
        self.offsetRect(r)
        self.view.canvas.RefreshRect(r, False)
        if not self._data: return
        
        channel = int((x - 60) / self.CHANNEL_WIDTH) + 1
        timeZoom = int(self.view.ToolBar.time.Value)
        time = int((y * timeZoom) / self._step) * self._samplingRate
        t = (self._samplingRate, channel, time)
        self.view.status = 'Sampling Rate: %2.3f ms - Channel: %s. Time: %s ms' % t
    
    def click(self, position):
        if not self._data: return
        
        path = self._path.replace('.txt', '.picking.txt')
        data = {}
        for i in range(1, 25): data[i] = ''
        if os.path.lexists(path):
            f = open(path, 'r')
            lines = [line.strip() for line in f.readlines()]
            f.close()
            for line in lines:
                d = line.split(':')
                if len(d) != 2: continue
            
                try: data[int(d[0])] = d[1].strip()
                except: pass
        x, y = self.convertEventCoords(position[0], position[1])
        channel = int((x - 60) / self.CHANNEL_WIDTH) + 1
        timeZoom = int(self.view.ToolBar.time.Value)
        time = int((y * timeZoom) / self._step) * self._samplingRate
        data[channel] = '%2.3f ms' % time
        f = open(path, 'w')
        for datum in data:
            s = '%02.0f: %s\n' % (datum, data[datum])
            f.write(s)
        f.close()
    
    def changeAmplitude(self, zoom):
        self.draw(self._path)
        
    def changeTime(self, zoom):
        self.draw(self._path)
        